/**
 * @file	TubeScreamer.h
 * @author  Thomas Fu <thomas.ks.fu@gmail.com>
 * @version 1.0
 *
 * @section LICENSE
 *
 * This program is propety of The SOSS and may not be used by any 
 * individual for any purpose at any time without express permission from 
 * Mike Casey, Thomas Fu, Chris Hairfield, Kyle Lamson, Ben Treweek, or Cliff 
 * Warren.
 *
 * @brief
 * This Effect subclass is an emulator of the Ibanez Tube Screamer overdrive 
 * pedal
 *
 * @class TubeScreamer
 */

#ifndef _tubescreamer_h
#define _tubescreamer_h

#include <cstdlib>
#include <iostream>
#include <fstream>
#include "IODataTypes.h"
#include "Distortion.h"
#include "LinearModule.h"
#include "FastNN.h"
#include "Effect.h"
#include "IIRFilter.h"

class TubeScreamer: public Effect
{
	public: 
		
		/** 
		 * Default constructor for the TubeScreamer effect with middle values for 
		 * volume, gain, and tone
		 */
		TubeScreamer();
		
		/**
		 * Constructor for the TubeScreamer effect that specifies values for volume,
		 * gain, and tone.
		 *
		 * @param volume A value between 0 and 100 specifying the amount of 
		 * post-overdrive amplification of the signal
		 *
		 * @param gain A value between 0 and 100 specifying the amount of distortion
		 * to be added to the signal
		 *
		 * @param tone A double between 0 and 100 that changes the output tone of 
		 * the Tube Screamer (0 corresponds to a more muddy, bassy sound whereas
		 * 100 corresponds to a more trebly sound).
		 *
		 * @param dirty A double between 0 and 100 that specifies the relative level
		 * of the distorted signal to the clean signal
		 */
		TubeScreamer(double volume, double gain, double tone, double dirty);
	
		/** Destructor for the TubeScreamer class */
		~TubeScreamer();
		
		/**
		 * Function that processes the data from the input buffer through an 
		 * emulator of the Ibanez Tube Screamer pedal to produce an overdriven
		 * version of the input buffer at the output buffer.
		 *
		 * @param outputBuffer The buffer of data to be written to the output of the 
		 * program (currently the speakers of the computer)
		 *
		 * @param inputBuffer The buffer of data read from the input to the program
		 * (either the line-in port or the built-in microphone)
		 *
		 * @param data A pointer to a processData struct cast as a void*
		 *
		 * @return An integer encoding information about the successful execution of 
		 * this function. A zero indicates successful execution with no problems.
		 */
		int processSound(void *outputBuffer, void *inputBuffer, void *data);

	private:
	
	FastNN *transferFunction;
	
	LinearModule *highPass, *lowPass, *highShelfFilter;
	
		/**
		 * Function to initialize the IIR Filters used in the Ibanez Tube Screamer
		 * emulator. 
		 *
		 * @param highPass The filter used in the initial high pass stage of the 
		 * Tube Screamer emulator. This is a simple one-pole high-pass Butterworth
		 * filter with a cutoff frequency of 720.484 Hz
		 *
		 * @param lowPass The filter used in the post-overdrive low pass stage of  
		 * the Tube Screamer emulator. This is a simple one-pole low-pass 
		 * Butterworth filter with a cutoff frequency of 720.484 Hz
		 *
		 * @param highPass The filter used in the initial high pass stage of the 
		 * Tube Screamer emulator. This is a simple one-pole high-pass Butterworth
		 * filter with a cutoff frequency of 720.484 Hz
		 */
		void initializeTubeScreamer(IIRFilter &highPass, IIRFilter &lowPass, 
										IIRFilter* & highShelfFilter, double tone);

		/**
		 * A value between 0 and 100 specifying the amount of distortion to be added
		 * to the signal
		 */
		double gain;
	
		/**
		 * A double between 0 and 100 that changes the output tone of the Tube
		 * Screamer (0 corresponds to a more muddy, bassy sound whereas 100 
		 * corresponds to a more trebly sound).
		 */
		double tone;
	
		/**
		 * A value between 0 and 100 specifying the amount of post-overdrive 
		 * amplification of the signal
		 */
		double volume;

		/**
		 * A value between 0 and 100 specifying the relative amount of distorted
		 * signal versus clean signal.
		 */
		double dirty;
};

#endif